home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / utils / gdb36p4s.zoo / m68k-pinsn.c < prev    next >
C/C++ Source or Header  |  1993-09-04  |  21KB  |  909 lines

  1. /* Print m68k instructions for GDB, the GNU debugger.
  2.    Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. GDB is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GDB is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GDB; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21.  
  22. #include <setjmp.h>
  23. #include <signal.h>
  24.  
  25. #include "defs.h"
  26. #include "param.h"
  27. #include "symtab.h"
  28. #include "opcode.h"
  29.  
  30. /* 68k instructions are never longer than this many bytes.  */
  31. #define MAXLEN 22
  32.  
  33. /* Number of elements in the opcode table.  */
  34. #define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
  35.  
  36. extern char *reg_names[];
  37. char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
  38.              "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
  39.  
  40. static unsigned char *print_insn_arg ();
  41. static unsigned char *print_indexed ();
  42. static void print_base ();
  43. static int fetch_arg ();
  44.  
  45. #define NEXTBYTE(p)  (p += 2, ((char *)p)[-1])
  46.  
  47. #define NEXTWORD(p)  \
  48.   (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
  49.  
  50. #define NEXTLONG(p)  \
  51.   (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
  52.  
  53. #define NEXTSINGLE(p) \
  54.   (p += 4, *((float *)(p - 4)))
  55.  
  56. #define NEXTDOUBLE(p) \
  57.   (p += 8, *((double *)(p - 8)))
  58.  
  59. #if defined (atarist) && defined (__M68881__)
  60. #define NEXTEXTEND(p) \
  61.   (p += 12, *(long double *) (p - 12))
  62. #else
  63. #define NEXTEXTEND(p) \
  64.   (p += 12, 0.0)    /* Need a function to convert from extended to double
  65.                precision... */
  66. #endif
  67.  
  68. #define NEXTPACKED(p) \
  69.   (p += 12, 0.0)    /* Need a function to convert from packed to double
  70.                precision.   Actually, it's easier to print a
  71.                packed number than a double anyway, so maybe
  72.                there should be a special case to handle this... */
  73.  
  74. /* Print the m68k instruction at address MEMADDR in debugged memory,
  75.    on STREAM.  Returns length of the instruction, in bytes.  */
  76.  
  77. int
  78. print_insn (memaddr, stream)
  79.      CORE_ADDR memaddr;
  80.      FILE *stream;
  81. {
  82.   unsigned char buffer[MAXLEN];
  83.   register int i;
  84.   register unsigned char *p;
  85.   register const char *d;
  86.   register int bestmask;
  87.   int best;
  88.  
  89.   read_memory (memaddr, buffer, MAXLEN);
  90.  
  91.   bestmask = 0;
  92.   best = -1;
  93.   for (i = 0; i < NOPCODES; i++)
  94.     {
  95.       register unsigned int opcode = m68k_opcodes[i].opcode;
  96.       register unsigned int match = m68k_opcodes[i].match;
  97.       if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
  98.       && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
  99.       && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
  100.       && ((0xff & buffer[3] & match) == (0xff & opcode)))
  101.     {
  102.       /* Don't use for printout the variants of divul and divsl
  103.          that have the same register number in two places.
  104.          The more general variants will match instead.  */
  105.       for (d = m68k_opcodes[i].args; *d; d += 2)
  106.         if (d[1] == 'D')
  107.           break;
  108.  
  109.       /* Don't use for printout the variants of most floating
  110.          point coprocessor instructions which use the same
  111.          register number in two places, as above. */
  112.       if (*d == 0)
  113.         for (d = m68k_opcodes[i].args; *d; d += 2)
  114.           if (d[1] == 't')
  115.         break;
  116.  
  117.       if (*d == 0 && match > bestmask)
  118.         {
  119.           best = i;
  120.           bestmask = match;
  121.         }
  122.     }
  123.     }
  124.  
  125.   /* Handle undefined instructions.  */
  126.   if (best < 0)
  127.     {
  128.       fprintf_filtered (stream, "0%o", (buffer[0] << 8) + buffer[1]);
  129.       return 2;
  130.     }
  131.  
  132.   fprintf_filtered (stream, "%s", m68k_opcodes[best].name);
  133.  
  134.   /* Point at first word of argument data,
  135.      and at descriptor for first argument.  */
  136.   p = buffer + 2;
  137.   
  138.   /* Why do this this way? -MelloN */
  139.   for (d = m68k_opcodes[best].args; *d; d += 2)
  140.     {
  141.       if (d[0] == '#')
  142.     {
  143.       if (d[1] == 'l' && p - buffer < 6)
  144.         p = buffer + 6;
  145.       else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
  146.         p = buffer + 4;
  147.     }
  148.       if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
  149.     p = buffer + 4;
  150.       if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
  151.     p = buffer + 6;
  152.       if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
  153.     p = buffer + 4;
  154.     }
  155.  
  156.   d = m68k_opcodes[best].args;
  157.  
  158.   if (*d)
  159.     fputs_filtered (" ", stream);
  160.  
  161.   while (*d)
  162.     {
  163.       p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
  164.       d += 2;
  165.       if (*d && *(d - 2) != 'I' && *d != 'k')
  166.     fputs_filtered (",", stream);
  167.     }
  168.   return p - buffer;
  169. }
  170.  
  171. static unsigned char *
  172. print_insn_arg (d, buffer, p, addr, stream)
  173.      const char *d;
  174.      unsigned char *buffer;
  175.      register unsigned char *p;
  176.      CORE_ADDR addr;        /* PC for this arg to be relative to */
  177.      FILE *stream;
  178. {
  179.   register int val;
  180.   register int place = d[1];
  181.   int regno;
  182.   register char *regname;
  183.   register unsigned char *p1;
  184.   register double flval;
  185.   int flt_p;
  186.  
  187.   switch (*d)
  188.     {
  189.     case 'C':
  190.       fprintf_filtered (stream, "ccr");
  191.       break;
  192.  
  193.     case 'S':
  194.       fprintf_filtered (stream, "sr");
  195.       break;
  196.  
  197.     case 'U':
  198.       fprintf_filtered (stream, "usp");
  199.       break;
  200.  
  201.     case 'J':
  202.       {
  203.     static const struct { const char *name; int value; } names[]
  204.       = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
  205.          {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
  206.          {"msp", 0x803}, {"isp", 0x804}};
  207.  
  208.     val = fetch_arg (buffer, place, 12);
  209.     for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
  210.       if (names[regno].value == val)
  211.         {
  212.           fprintf_filtered (stream, names[regno].name);
  213.           break;
  214.         }
  215.     if (regno < 0)
  216.       fprintf_filtered (stream, "%d", val);
  217.       }
  218.       break;
  219.  
  220.     case 'Q':
  221.       val = fetch_arg (buffer, place, 3);
  222.       if (val == 0) val = 8;
  223.       fprintf_filtered (stream, "#%d", val);
  224.       break;
  225.  
  226.     case 'M':
  227.       val = fetch_arg (buffer, place, 8);
  228.       if (val & 0x80)
  229.     val = val - 0x100;
  230.       fprintf_filtered (stream, "#%d", val);
  231.       break;
  232.  
  233.     case 'T':
  234.       val = fetch_arg (buffer, place, 4);
  235.       fprintf_filtered (stream, "#%d", val);
  236.       break;
  237.  
  238.     case 'D':
  239.       fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
  240.       break;
  241.  
  242.     case 'A':
  243.       fprintf_filtered (stream, "%s",
  244.             reg_names[fetch_arg (buffer, place, 3) + 010]);
  245.       break;
  246.  
  247.     case 'R':
  248.       fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
  249.       break;
  250.  
  251.     case 'F':
  252.       fprintf_filtered (stream, "fp%d", fetch_arg (buffer, place, 3));
  253.       break;
  254.  
  255.     case 'O':
  256.       val = fetch_arg (buffer, place, 6);
  257.       if (val & 0x20)
  258.     fprintf_filtered (stream, "%s", reg_names [val & 7]);
  259.       else
  260.     fprintf_filtered (stream, "%d", val);
  261.       break;
  262.  
  263.     case '+':
  264.       fprintf_filtered (stream, "%s@+",
  265.             reg_names[fetch_arg (buffer, place, 3) + 8]);
  266.       break;
  267.  
  268.     case '-':
  269.       fprintf_filtered (stream, "%s@-",
  270.            reg_names[fetch_arg (buffer, place, 3) + 8]);
  271.       break;
  272.  
  273.     case 'k':
  274.       if (place == 'k')
  275.     fprintf_filtered (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
  276.       else if (place == 'C')
  277.     {
  278.       val = fetch_arg (buffer, place, 7);
  279.       if ( val > 63 )        /* This is a signed constant. */
  280.         val -= 128;
  281.       fprintf_filtered (stream, "{#%d}", val);
  282.     }
  283.       else
  284.     error ("Invalid arg format in opcode table: \"%c%c\".",
  285.            *d, place);
  286.       break;
  287.  
  288.     case '#':
  289.     case '^':
  290.       p1 = buffer + (*d == '#' ? 2 : 4);
  291.       if (place == 's')
  292.     val = fetch_arg (buffer, place, 4);
  293.       else if (place == 'C')
  294.     val = fetch_arg (buffer, place, 7);
  295.       else if (place == '8')
  296.     val = fetch_arg (buffer, place, 3);
  297.       else if (place == '3')
  298.     val = fetch_arg (buffer, place, 8);
  299.       else if (place == 'b')
  300.     val = NEXTBYTE (p1);
  301.       else if (place == 'w')
  302.     val = NEXTWORD (p1);
  303.       else if (place == 'l')
  304.     val = NEXTLONG (p1);
  305.       else
  306.     error ("Invalid arg format in opcode table: \"%c%c\"."